package com.tyc.aqs;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

/**
 * 实现允许两个线程获取锁
 * 共享式与独占式的重要区别
 *  1.返回值>0 成功获取，判断条件(setHeadAndPropagate)满足则进入循环修改头节点状态或传播唤醒等待节点，结束
 *  2. 释放时要保证线程安全（tryRealiseShare）
 */
public class TwinsLock {
    private final Sync sync = new Sync();
    private static  class Sync extends AbstractQueuedSynchronizer{
        public Sync() {
            setState(2);
        }

        //返回值大于等于0表示获取锁成功
        @Override
        protected int tryAcquireShared(int arg) {
            for(;;){
                int state = getState();
                int target = state - arg;
                if(target<0 || compareAndSetState(state,target)){
                    return target;
                }
            }
        }

        @Override
        protected boolean tryReleaseShared(int arg) {
            for (;;){
                int state = getState();
                int target = state + arg;
                if(compareAndSetState(state,target)){
                    return true;
                }
            }
        }
    }
    public void lock(){
        sync.acquireShared(1);
    }

    public void unLock(){
        sync.releaseShared(1);
    }
}

class TestTTwinsLock{
    private static final TwinsLock twinsLock= new TwinsLock();
    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                twinsLock.lock();
                try {
                    System.out.println(Thread.currentThread().getName());
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    twinsLock.unLock();
                }
            }).start();
        }

        TimeUnit.SECONDS.sleep(20);
    }
}
